package com.bestcem.xm.member.dao;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bestcem.xm.label.grpc.service.param.LabelValueIdParam;
import com.bestcem.xm.member.entity.pojo.ExtendFieldDO;
import com.bestcem.xm.member.entity.pojo.ExtendFieldEnumItemDO;
import com.bestcem.xm.member.entity.pojo.MemberDO;
import com.bestcem.xm.member.enums.DeliveryTypeEnum;
import com.bestcem.xm.member.enums.MemberStatusEnum;
import com.bestcem.xm.member.enums.MemberTypeEnum;
import com.bestcem.xm.member.grpc.service.param.member.MemberQuery;
import com.bestcem.xm.member.service.param.DeliveryMembersDynamicSql;
import com.bestcem.xm.member.service.param.FuzzyMemberDynamicSql;
import com.bestcem.xm.member.service.param.SelectMemberDynamicSql;
import com.bestcem.xm.member.service.param.UpdateMemberGroupDynamicSql;

import javax.annotation.Nullable;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 联系人持久层接口
 *
 * @author yf.wang <yf.wang@idiaoyan.com>
 * @version V1.0
 * @date 2021/7/16
 */
public interface MemberDao {
    /**
     * 分页获取激活的企业联系人
     *
     * @param orgId  企业id
     * @param offset 企业id
     * @param size   企业id
     * @return 分页联系人
     */
    List<MemberDO> listOrgMembers(String orgId, Integer memberType, Integer offset, Integer size);

    /**
     * 获取激活的企业联系人总数
     *
     * @param orgId 企业id
     * @return 企业联系人数
     */
    Long countOrgMembers(String orgId, Integer memberType);

    /**
     * 获取联系人列表
     *
     * @param orgId
     * @param ids
     * @return
     */
    List<MemberDO> list(String orgId, List<String> ids);

    /**
     * 查询时间范围内的联系人
     * [startCreateTime,endCreateTime] & [startCreateTime,endCreateTime]
     *
     * @param orgId           企业标识
     * @param startCreateTime 创建时间左闭区间
     * @param endCreateTime   创建时间右闭区间
     * @param startUpdateTime 更新时间左闭区间
     * @param endUpdateTime   更新时间右闭区间
     * @return 联系人列表
     */
    List<MemberDO> listMemberByPeriod(String orgId, Date startCreateTime, Date endCreateTime, Date startUpdateTime, Date endUpdateTime);

    /**
     * 查询手机号、邮箱在参数范围内的联系人
     *
     * @param orgId  企业标识
     * @param type   联系人类型
     * @param phones 手机号集合
     * @return 联系人集合
     */
    List<MemberDO> listMembersByPhones(String orgId, Integer type, Collection<String> phones);

    /**
     * 批量查询邮箱在参数范围内的联系人
     *
     * @param orgId  企业标识
     * @param type   联系人类型
     * @param emails 邮箱集合
     * @return 联系人集合
     */
    List<MemberDO> listMembersByEmails(String orgId, Integer type, Collection<String> emails);

    /**
     * 查询企业个人联系人数量
     *
     * @param orgId 企业标识
     * @return 个人联系人数量
     * @author dc.wang <dc.wang@idiaoyan.com>
     * @date 2021/8/30
     */
    Long countIndividualMember(String orgId);


    /**
     * 根据条件获取数据
     *
     * @param orgId
     * @param instituteName
     * @param status
     * @return
     */
    Integer countByOrgIdAndInstituteNameAndNotEqualStatus(String orgId, String instituteName, int status);

    /**
     * 根据 id 更新联系人状态
     *
     * @param ids
     * @param status
     * @return
     */
    long updateStatusByIds(List<String> ids, int status);

    /**
     * 开放平台批量创建/更新联系人，完全覆盖更新
     *
     * @param members 联系人列表
     * @return 更新结果，顺序与members对应 true 更新成功
     * @author dc.wang <dc.wang@idiaoyan.com>
     * @date 2021/11/9
     */
    List<Boolean> batchUpsertOpenPlatformMembers(List<MemberDO> members);

    /**
     * 通过邮箱号查询未被软删除的联系人
     *
     * @param orgId      企业标识
     * @param memberType 联系人类型
     * @param email      邮箱号
     * @return member
     */
    MemberDO findUndeletedMemberByEmail(String orgId, Integer memberType, String email);

    /**
     * 通过手机号查询未被软删除的联系人
     *
     * @param orgId      企业标识
     * @param memberType 联系人类型
     * @param phone      手机号
     * @return member
     */
    MemberDO findUndeletedMemberByPhone(String orgId, Integer memberType, String phone);

    /**
     * 查询微信小程序用户
     * @param orgId
     * @param memberType
     * @param appId
     * @param openId
     * @return member
     */
    MemberDO findByAppIdAndOpenId(String orgId, Integer memberType, String appId, String openId);

    /**
     * 查询微信小程序用户
     * @param orgId
     * @param memberType
     * @param appId
     * @param openId
     * @return
     */
    List<MemberDO> listByAppIdAndOpenId(String orgId, Integer memberType, String appId, String openId);

    /**
     * 根据条件获取数据
     *
     * @param orgId
     * @param mobile
     * @param email
     * @param aliPayUserId
     * @param openId
     * @param outNo
     * @param mType
     * @param statusList
     * @return
     */
    List<MemberDO> findByOrgIdAndMobileAndEmailAndAliPayUserIdAndOpenidAndAttribute(String orgId, String mobile,
                                                                                    String email, String aliPayUserId,
                                                                                    String openId, String outNo, Integer mType,
                                                                                    List<Integer> statusList);

    /**
     * 模糊搜索联系人
     *
     * @param orgId            企业标识
     * @param regex            关键字 匹配联系人姓名、手机号
     * @param memberTypeEnum   联系人类型
     * @param deliveryTypeEnum 联系方式
     * @author dc.wang <dc.wang@idiaoyan.com>
     * @date 2021/8/2
     */
    Long countByContactInfo(String orgId, String regex, MemberTypeEnum memberTypeEnum, DeliveryTypeEnum deliveryTypeEnum);

    List<MemberDO> listByContactInfo(String orgId, String regex, MemberTypeEnum memberTypeEnum, DeliveryTypeEnum deliveryTypeEnum, int page, int size);

    /**
     * 模糊搜索企业联系人
     *
     * @param orgId            企业标识
     * @param regex            关键字 匹配机构名、手机号、对接人
     * @param deliveryTypeEnum 联系方式
     * @author dc.wang <dc.wang@idiaoyan.com>
     * @date 2021/8/2
     */
    Long countInstituteMembersByContactInfo(String orgId, String regex, DeliveryTypeEnum deliveryTypeEnum);

    List<MemberDO> listInstituteMembersByContactInfo(String orgId, String regex, DeliveryTypeEnum deliveryTypeEnum, int page, int size);

    /**
     * 根据 组织id和联系人类型 更新联系人状态
     *
     * @param status
     * @param orgId
     * @param attribute
     * @return
     */
    Boolean updateStatusByOrgIdAndAttribute(int status, String orgId, Integer attribute);

    /**
     * 过滤 member
     *
     * @param queryWrapper
     * @return
     */
    List<MemberDO> filterMembers(FuzzyMemberDynamicSql queryWrapper);

    /**
     * 查询投放条件解析联系人数量
     *
     * @param dynamicSql 查询参数
     * @return 联系人总数
     */
    Integer countDeliveryMembers(DeliveryMembersDynamicSql dynamicSql);

    /**
     * 分页查询投放条件解析联系人
     * 注：分页参数不存在查询所有
     *
     * @param dynamicSql 查询参数
     * @return 联系人集合
     */
    List<MemberDO> listDeliveryMembers(DeliveryMembersDynamicSql dynamicSql);

    /**
     * 根据条件获取数据
     *
     * @param orgId
     * @param instituteName
     * @param status
     * @return
     */
    List<MemberDO> findByOrgIdAndInstituteNameAndStatusNot(String orgId, String instituteName, Integer status);

    /**
     * 根据条件获取数据
     *
     * @param name
     * @param mType
     * @param status
     * @return
     */
    MemberDO findOneByNameAndMtypeAndStatusNe(String name, int mType, int status);

    /**
     * 根据id列表获取联系人信息
     *
     * @param ids
     * @return
     */
    List<MemberDO> findByIds(List<String> ids);

    /**
     * 根据userId查询用户信息
     *
     * @param orgId  企业id
     * @param userId 用户id
     * @return member
     */
    MemberDO findByUserId(String orgId, String userId);

    /**
     * 根据 不同参数获取数据
     *
     * @param wrapper
     * @return
     */
    List<MemberDO> findByParam(QueryWrapper wrapper);

    /**
     * 批量更新联系人扩展字段名
     *
     * @param orgId      企业id
     * @param memberType 联系人类型
     * @param fieldEnums 扩展字段枚举信息
     */
    void updateMemberFieldEnumValue(String orgId, Integer memberType, List<ExtendFieldEnumItemDO> fieldEnums);

    /**
     * 批量更新联系人扩展字段名
     *
     * @param orgId  企业id
     * @param fields 扩展字段信息
     */
    void batchUpdateFieldName(String orgId, Integer memberType, List<ExtendFieldDO> fields);

    /**
     * 移除联系人扩展字段信息
     *
     * @param orgId    企业id
     * @param fieldIds 扩展字段id集合
     */
    void batchDeleteExtendFields(@NotNull String orgId, @NotNull Integer memberType, @NotEmpty Collection<String> fieldIds);

    /**
     * 保存标签
     *
     * @param modifiedMemberLabelMap
     * @return
     */
    void saveLabels(Map<String, List<LabelValueIdParam>> modifiedMemberLabelMap);

    /**
     * 获取 orgId 下 指定 field value 的 联系人类型为 memberType 且状态为 status 的联系人
     *
     * @param orgId
     * @param field
     * @param value
     * @param memberType
     * @param status
     * @return
     */
    MemberDO findByOrgIdAndFieldAndAttributeAndStatus(String orgId, String field, String value, Integer memberType, Integer status);

    /**
     * 手动 （联系人来源） 创建联系人
     *
     * @param member
     * @return
     */
    MemberDO manualSave(MemberDO member);

    /**
     * 获取 orgId 下 指定 field value 的 联系人类型为 memberType  的联系人
     *
     * @param orgId
     * @param field
     * @param value
     * @param memberType
     * @return
     */
    MemberDO findByOrgIdAndFieldAndMemberType(String orgId, String field, String value, Integer memberType);

    /**
     * 根据id 获取联系人数据
     *
     * @param id
     * @return
     */
    MemberDO findById(String id);

    /**
     * 分页模糊查询联系人
     *
     * @param orgId      企业标识
     * @param memberType 联系人类型，为空时不区分类型
     * @param regexName  联系人名称模糊搜索参数，为空时不校验名称
     * @param offset     分页偏移量
     * @param size       分页大小
     * @return 联系人集合
     */
    List<MemberDO> listMembersByRegexName(@NotNull String orgId,
                                        @Nullable Integer memberType,
                                        @Nullable String regexName,
                                        @NotNull Integer offset,
                                        @NotNull Integer size);

    Integer countMembersByRegexName(@NotNull String orgId,
                                    @Nullable Integer memberType,
                                    @Nullable String regexName);

    /**
     * 更新联系人
     *
     * @param member
     */
    void updateMember(MemberDO member, Boolean supportGroupToken);

    /**
     * excel（来源） 创建联系人
     *
     * @param member
     * @return
     */
    MemberDO importSave(MemberDO member);

    /**
     * 统计当前企业的联系人数量
     *
     * @param orgId
     * @return
     */
    Integer countSlice(String orgId);

    /**
     * 获取联系人切片
     *
     * @param orgId
     * @param startOffset
     * @param pageSize
     * @return
     */
    List<MemberDO> findSlice(String orgId, String startOffset, int pageSize);

    /**
     * 获取分片中的最后一个联系人
     *
     * @param orgId
     * @param startOffset
     * @param pageSize
     * @return
     */
    MemberDO findLastInSlice(String orgId, String startOffset, int pageSize);

    /**
     * 创建内部联系人
     *
     * @param innerMemeber
     * @return
     */
    MemberDO createInnerMemberByCreateUser(MemberDO innerMemeber);

    /**
     * 通过动态sql 查询
     *
     * @param queryWrapper
     * @return
     */
    Integer countByDynamicSql(SelectMemberDynamicSql queryWrapper);

    /**
     * 通过动态sql 查询
     *
     * @param dynamicSql
     * @return
     */
    List<MemberDO> filterMembersByDynamicSql(SelectMemberDynamicSql dynamicSql);

    /**
     * 问卷创建联系人
     *
     * @param newMember
     * @return
     */
    MemberDO surveySaveMember(MemberDO newMember);

    /**
     * 投放创建联系人
     *
     * @param member
     * @return
     */
    MemberDO deliverSaveMember(MemberDO member);

    /**
     * 获取该组织下 指定联系人的数量
     *
     * @param orgId
     * @param memberType
     * @return
     */
    Long countOrgMember(String orgId, Integer memberType);

    /**
     * 统计联系人数量
     * 若 orgId 存在则统计 改orgId 下的联系人数量
     *
     * @param orgId
     * @return
     */
    Long countMember(String orgId);

    /**
     * 获取激活的企业联系人总数
     *
     * @param orgId
     * @param memberType
     * @param status
     * @return
     */
    Long countMember(String orgId, Integer memberType, Integer status);

    /**
     * 查询联系人
     *
     * @param orgId
     * @param start
     * @param batchCount
     */
    List<MemberDO> findMember(String orgId, int start, Integer batchCount);

    /**
     * 获取改组织下 指定状态的联系人
     *
     * @param orgId
     * @param status
     * @return
     */
    List<MemberDO> findByOrgIdAndStatus(String orgId, int status);

    /**
     * 批量保存联系人
     *
     * @param memberList
     */
    void batchSave(List<MemberDO> memberList);

    /**
     * 查询个人联系人数量
     *
     * @param orgId
     * @param memberType
     * @param startCreateTime
     * @param endCreateTime
     * @param startUpdateTime
     * @param endUpdateTime
     * @return
     */
    Long countByPeriod(String orgId, int memberType, Date startCreateTime, Date endCreateTime, Date startUpdateTime, Date endUpdateTime);

    /**
     * 查询联系人
     *
     * @param orgId
     * @param memberType
     * @param startCreateTime
     * @param endCreateTime
     * @param startUpdateTime
     * @param endUpdateTime
     * @param offset
     * @param size
     * @return
     */
    List<MemberDO> listMemberByPeriod(String orgId, int memberType, Date startCreateTime, Date endCreateTime, Date startUpdateTime, Date endUpdateTime, Integer offset, Integer size);

    /**
     * 获取数据
     *
     * @param orgId
     * @param memberType
     * @param instituteName
     * @param status
     * @return
     */
    List<MemberDO> findByOrgIdAndMemberTypeAndInstituteNameAndStatusNot(String orgId, int memberType, String instituteName, int status);


    /**
     * 查询拥有GroupSyncToken的联系人（表示分组还未完成）
     *
     * @param orgId
     * @param memberType
     * @param status
     * @return
     */
    MemberDO findOneByOrgIdAndMemberTypeAndStatusAndGroupSyncToken(String orgId, int memberType, int status);

    /**
     * 根据联系人id和状态查询联系人
     *
     * @param memberId
     * @param orgId
     * @param memberType
     * @param status
     * @return
     */
    MemberDO findOneByIdAndStatus(String memberId, String orgId, int memberType, int status);

    /**
     * 更新联系人的分组令牌
     *
     * @param memberId
     * @param newGroupSyncToken
     * @param oldGroupSyncToken
     */
    void updateMemberGroupSyncToken(String memberId, String newGroupSyncToken, String oldGroupSyncToken);

    /**
     * 更新联系人的groups（分组）字段
     *
     * @param groups
     * @param memberId
     * @param groupSyncToken
     * @return
     */
    Integer updateMemberGroups(String groups, String memberId, String groupSyncToken);

    /**
     * 根据 组织id 联系人类型 状态 以及分组 统计数据
     *
     * @param orgId
     * @param memberType
     * @param status
     * @param seq
     * @return
     */
    Long countByOrgIdAndMemberTypeAndStatusAndSeq(String orgId, int memberType, int status, Long seq);

    /**
     * 删除联系人指定分组
     *
     * @param orgId
     * @param memberType
     * @param status
     * @param seq
     * @param startTime
     * @param endTime
     */
    void deleteGroup(String orgId, int memberType, int status, Long seq, Date startTime, Date endTime);

    /**
     * 根据 orgId memberType status  endTime 查询联系人
     *
     * @param orgId      公司id
     * @param memberType 联系人类型
     * @param status     联系人状态
     * @param endTime    结束时间
     * @param offset     偏移量
     * @param limit      限制
     * @author ympan <yuming.pan@idiaoyan.com>
     * @date 14:06 2022/1/17
     */
    MemberDO findOneByOrgIdAndMemberTypeAndStatusAndCreateTime(String orgId, int memberType, int status, Date endTime, long offset, int limit);

    /**
     * 根据 orgId memberType status  currTime 查询联系人
     *
     * @param orgId      公司id
     * @param memberType 联系人类型
     * @param status     联系人状态
     * @param currTime   当前时间
     * @author ympan <yuming.pan@idiaoyan.com>
     * @date 14:06 2022/1/17
     */
    Long countByOrgIdAndMemberTypeAndStatusAndCreateTime(String orgId, int memberType, int status, Date currTime);

    /**
     * 根据 orgId memberType status seq currTime 查询联系人数量
     *
     * @param orgId      公司id
     * @param memberType 联系人类型
     * @param status     联系人状态
     * @param seq        分组seq
     * @param currTime   当前时间
     * @author ympan <yuming.pan@idiaoyan.com>
     * @date 14:06 2022/1/17
     */
    Long countByOrgIdAndMemberTypeAndStatusAndGroupsAndCreateTime(String orgId, int memberType, int status, Long seq, Date currTime);

    /**
     * 根据 orgId memberType status seq endTime 查询联系人
     *
     * @param orgId      公司id
     * @param memberType 联系人类型
     * @param status     联系人状态
     * @param seq        分组seq
     * @param endTime    当前时间
     * @author ympan <yuming.pan@idiaoyan.com>
     * @date 14:06 2022/1/17
     */
    MemberDO findOneByOrgIdAndMemberTypeAndStatusAndGroupsAndCreateTime(String orgId, int memberType, int status, Long seq, Date endTime, long offset, int limit);

    /**
     * 通过动态查询条件更新联系人
     *
     * @param dynamicSql 动态sql
     * @return 影响行数
     * @author ympan <yuming.pan@idiaoyan.com>
     * @date 16:13 2022/1/17
     */
    Integer updateMembersByDynamicSql(UpdateMemberGroupDynamicSql dynamicSql);

    /**
     * 删除联系人
     *
     * @param dynamicSql
     * @param size
     * @return
     */
    List<String> deleteFilterMembers(SelectMemberDynamicSql dynamicSql, int size);

    /**
     * 获取数据
     *
     * @param orgId
     * @param outNo
     * @param memberType
     * @param index
     * @return
     */
    MemberDO findOneByOrgIdAndOutNoAndAttributeAndStatus(String orgId, String outNo, Integer memberType, int index);

    /**
     * 获取数据
     *
     * @param orgId
     * @param individual
     * @param activated
     * @param appId
     * @param openId
     * @return
     */
    MemberDO findOneByOrgIdAndMemberTypeAndStatusAndAppIdAndOpenId(String orgId, MemberTypeEnum individual, MemberStatusEnum activated, String appId, String openId);

    /**
     * 微信同步联系人
     *
     * @param memberDO
     */
    String wechatSaveMember(MemberDO memberDO);

    List<MemberDO> findByWx(Integer memberType, String orgId, Integer status, List<MemberQuery> queryParams);

    /**
     * 根据修改时间获取数据
     *
     * @param time
     * @param start
     * @param batchCount
     * @return
     */
    List<MemberDO> findByUpdateTimeAfter(String time, int start, int batchCount);
}
